Completed
Push — master ( f2f9ef...8d6f66 )
by Fike
56s queued 19s
created

Normalizer.deserializer   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
c 0
b 0
f 0
nc 4
dl 0
loc 10
rs 9.4285
nop 2
1
var Objects = require('../Utility').Objects
2
var Defaults = require('./Defaults')
3
var Errors = require('../Error')
4
5
var Normalizer = {
6
  /**
7
   * @param {TStateTrigger|string} trigger
8
   * @return {TStateTrigger}
9
   */
10
  stateTrigger: function (trigger) {
11
    if (typeof trigger === 'string') {
12
      trigger = {id: trigger}
13
    }
14
    if (!Objects.isObject(trigger) || !trigger.id) {
15
      return null
16
    }
17
    var hints = trigger.hints
18
    if (!Objects.isObject(hints) && !Objects.isFunction(hints)) {
19
      trigger.hints = {}
20
    }
21
    return trigger
22
  },
23
  /**
24
   * Normalizes transition output.
25
   *
26
   * @param {TTransitionReturn|string} result
27
   * @return {TTransitionReturn}
28
   */
29
  transition: function (result) {
30
    result = Objects.copy(result, true)
31
    if (typeof result === 'string') {
32
      result = {trigger: result}
33
    } else if (!Objects.isObject(result)) {
34
      result = {}
35
    }
36
    result.trigger = Normalizer.stateTrigger(result.trigger)
37
    if (typeof result.transitionedTo !== 'string') {
38
      result.transitionedTo = null
39
    }
40
    return result
41
  },
42
  /**
43
   * @param {TState|Function} state
44
   * @param {TStateId} id
45
   * @param {object<string, (int|null)>} timeouts
46
   * @return {TState}
47
   */
48
  state: function (state, id, timeouts) {
49
    if (Objects.isFunction(state)) {
50
      state = {transition: state}
51
    }
52
    state = Objects.copy(state, true)
53
    state.id = typeof state.id === 'string' ? state.id : id
54
    state.entrypoint = !!state.entrypoint
55
    state.terminal = !!state.terminal
56
    var handler = state.transition || function () {}
57
    state.transition = Normalizer.handler(handler, 'transition', timeouts)
58
    handler = state.abort || function () {}
59
    state.abort = Normalizer.handler(handler, 'abort', timeouts)
60
    state.triggers = Normalizer.stateTrigger(state.triggers)
61
    if (!state.hasOwnProperty('timeout')) {
62
      state.timeout = timeouts.state
63
    }
64
    return state
65
  },
66
  /**
67
   * @param {TStateHandler|Function} handler
68
   * @param {string} id
69
   * @param {object<string, (int|null)>} timeouts
70
   *
71
   * @return {TStateHandler}
72
   */
73
  handler: function (handler, id, timeouts) {
74
    var cursor = handler && handler.handler
75
    var defaultHandler = function () { return cursor }
76
    handler = Normalizer.singleHandler(handler, defaultHandler, id, timeouts)
77
    if (handler.onTimeout) {
78
      var name = 'on' + id[0].toUpperCase() + id.substr(1) + 'Timeout'
79
      handler.onTimeout = Normalizer.handler(handler.onTimeout, name, timeouts)
80
    }
81
    return handler
82
  },
83
  /**
84
   * @param {TStateHandler|Function} handler
85
   * @param {Function} defaultHandler
86
   * @param {string} id
87
   * @param {object<string, (int|null)>} timeouts
88
   *
89
   * @return {TStateHandler}
90
   */
91
  singleHandler: function (handler, defaultHandler, id, timeouts) {
92
    if (Objects.isFunction(handler)) {
93
      handler = {handler: handler}
94
    }
95
    if (!Objects.isObject(handler)) {
96
      handler = {}
97
    }
98
    handler.id = id
99
    if (!Objects.isFunction(handler.handler)) {
100
      handler.handler = defaultHandler
101
    }
102
    if (!handler.hasOwnProperty('timeout')) {
103
      handler.timeout = timeouts[id]
104
    }
105
    return handler
106
  },
107
  /**
108
   * @param {TScenarioInput} input
109
   *
110
   * @return {TScenario}
111
   */
112
  scenario: function (input) {
113
    if (!Objects.isObject(input)) {
114
      throw new Errors.InvalidInputError('Provided scenario is not an object')
115
    }
116
    var scenario = Objects.copy(input, true)
117
    var timeouts = Objects.copy(Defaults.Timeouts)
118
    timeouts = Objects.merge(timeouts, input.timeouts || {})
119
    var handlers = ['onError', 'onTermination']
120
    handlers.forEach(function (name) {
121
      scenario[name] = Normalizer.handler(scenario[name], name, timeouts)
122
    })
123
    scenario.states = scenario.states || {}
124
    Object.keys(scenario.states).forEach(function (key) {
125
      scenario.states[key] = Normalizer.state(scenario.states[key], key, timeouts)
126
    })
127
    scenario.timeout = timeouts.scenario
128
    scenario.deserializer = Normalizer.deserializer(scenario.deserializer, timeouts)
129
    return scenario
130
  },
131
  /**
132
   * @param {THandler|Function|*} handler
133
   * @param {object.<string, (int|null)>} timeouts
134
   *
135
   * @return {TStateHandler}
136
   */
137
  deserializer: function (handler, timeouts) {
138
    if (!Objects.isObject(handler)) {
139
      handler = {handler: handler}
140
    }
141
    if (!Objects.isFunction(handler.handler)) {
142
      // TODO: pass logger options
143
      handler.handler = Defaults.Deserializer.factory()
144
    }
145
    return Normalizer.handler(handler, 'deserializer', timeouts)
146
  }
147
}
148
149
module.exports = {
150
  Normalizer: Normalizer
151
}
152